package com.sunriz.javafx.server.utils.modbus;


import cn.hutool.core.util.RandomUtil;
import com.serotonin.modbus4j.BasicProcessImage;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusSlaveSet;
import com.serotonin.modbus4j.ProcessImage;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.sunriz.javafx.server.utils.modbus.util.MyProcessImageListener;
import com.sunriz.javafx.server.utils.modbus.util.SerialPortWrapperImpl;

/**
 * 模拟从站设备
 * @author wusq
 * @date 2021/1/3
 */
public class RtuSlaveTest {

    public static void main(String[] args) {
        createRtuSlave();
    }

    public static void createRtuSlave(){
        // 设置串口参数，串口是COM2，波特率是9600
        SerialPortWrapperImpl wrapper = new SerialPortWrapperImpl("COM2", 115200,
                8,  // 数据位 8
                1,  // 停止位 1
                0,  // 无奇偶校验 0
                0,  // 输入流控制
                0); // 输出流控制

        // Modbus 工厂，可以创建 RTU、TCP 等不同类型的 Master 和 Slave
        ModbusFactory modbusFactory = new ModbusFactory();

        // 创建 RTU 从站
        final ModbusSlaveSet slave = modbusFactory.createRtuSlave(wrapper);

        // 设置过程影像（即寄存器的模拟）
        BasicProcessImage processImage = new BasicProcessImage(1);
        processImage.setInvalidAddressValue(Short.MIN_VALUE);
        slave.addProcessImage(processImage);

        // 添加监听器，监听 slave 线圈状态和保持寄存器的写入
        processImage.addListener(new MyProcessImageListener());

        // 初始化模拟寄存器
        setCoil(processImage);
        setInput(processImage);
        setHoldingRegister(processImage);
        setInputRegister(processImage);

        // 启动从站设备线程
        new Thread(() -> {
            try {
                slave.start();
            } catch (ModbusInitException e) {
                e.printStackTrace();
            }
        }).start();

        /*new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                // 间隔1秒修改从站设备1的保持寄存器数据
                updateHoldingRegister(slave.getProcessImage(1));
            }
        }, 1000, 1000);*/
    }

    // 模拟线圈状态
    private static void setCoil(ProcessImage processImage){
        processImage.setCoil(0, true);
        processImage.setCoil(1, false);
        processImage.setCoil(2, true);
    }

    // 模拟离散输入状态
    private static void setInput(ProcessImage processImage){
        processImage.setInput(0, false);
        processImage.setInput(1, true);
        processImage.setInput(2, false);
    }

    // 模拟保持寄存器的值
    private static void setHoldingRegister(ProcessImage processImage){
        processImage.setHoldingRegister(0, (short) 11);
        processImage.setHoldingRegister(1, (short) 22);
        processImage.setHoldingRegister(2, (short) 33);
    }

    // 模拟修改保持寄存器的值
    private static void updateHoldingRegister(ProcessImage processImage){
        processImage.setHoldingRegister(0, (short) RandomUtil.randomInt(0, 100));
        processImage.setHoldingRegister(1, (short) RandomUtil.randomInt(0, 100));
        processImage.setHoldingRegister(2, (short) RandomUtil.randomInt(0, 100));
    }

    // 模拟输入寄存器的值
    private static void setInputRegister(ProcessImage processImage){
        processImage.setInputRegister(0, (short) 44);
        processImage.setInputRegister(1, (short) 55);
        processImage.setInputRegister(2, (short) 66);
    }
}
